import tkinter as tk
import random
import math

# 球场大小（不能小于3×3）
w = 5
h = 3
# 球门中线
mid = math.floor(h / 2)
cen = math.floor(w / 2)
# 随机测试总次数
size = 10
# 当前动作状态与结果反馈
data = {}

# 初始化窗口
root = tk.Tk()
root.title("机器人足球训练")

# 创建画布
canvas = tk.Canvas(root, width=w * 60, height=h * 60)
canvas.pack()

# 玩家初始位置为发球区（球场中央）
move_a = [mid, cen - 1]  # 红方坐标：Y轴、X轴
move_b = [mid, cen + 1]  # 蓝方坐标：Y轴、X轴
# 默认蓝方持球
ball = 'b'
lens = size  # 剩余次数

# 绘制球场
def show():
    canvas.delete("all")
    for yi in range(h):
        for xi in range(w):
            css = ""
            if yi == mid and xi == 0:
                # 防守方球门坐标样式
                canvas.create_rectangle(xi * 60, yi * 60, (xi + 1) * 60, (yi + 1) * 60, fill="#E99")
            elif yi == mid and xi == (w - 1):
                # 进攻方球门坐标样式
                canvas.create_rectangle(xi * 60, yi * 60, (xi + 1) * 60, (yi + 1) * 60, fill="#99E")
            else:
                canvas.create_rectangle(xi * 60, yi * 60, (xi + 1) * 60, (yi + 1) * 60)

# 显示比赛动画（防守方位置，进攻方位置）
def play(ya, xa, yb, xb):
    # 清空场地
    canvas.delete("player")
    # 显示防守方运动员
    if ball == 'a':
        # 防守方持球
        canvas.create_text((xa * 60) + 30, (ya * 60) + 30, text="🕺\n⚽", fill="#F22", tags="player")
    else:
        canvas.create_text((xa * 60) + 30, (ya * 60) + 30, text="🕺", fill="#F22", tags="player")
    # 显示进攻方运动员
    if ball == 'b':
        # 进攻方持球
        canvas.create_text((xb * 60) + 30, (yb * 60) + 30, text="🚶‍♂️\n⚽", fill="#22F", tags="player")
    else:
        canvas.create_text((xb * 60) + 30, (yb * 60) + 30, text="🚶‍♂️", fill="#22F", tags="player")

# 返回合理的坐标值数组
def goto(y, x, to=0):
    y = int(y)
    x = int(x)
    # 设置最大坐标值
    max_h = int(h - 1)
    max_w = int(w - 1)
    if to == 1:  # 上
        y = y - 1 if y - 1 >= 0 else 0
    elif to == 2:  # 下
        y = y + 1 if y + 1 <= max_h else max_h
    elif to == 3:  # 左
        x = x - 1 if x - 1 >= 0 else 0
    elif to == 4:  # 右
        x = x + 1 if x + 1 <= max_w else max_w
    # Y轴、X轴
    return [y, x]

# 判断游戏是否结束
def game_over(y, x):
    global ball
    over = False
    # 判断输赢：（计分规则：胜方加3分，败方0分）
    if ball == 'b':  # 蓝方持球
        # 判断是否进入红方球门
        if y == mid and x == 0:
            print("蓝方胜利！")
            ball = 'a'  # 交换球权（输家持球）
            over = True
        # 判断乌龙球（进入自家球门）
        if y == mid and x == (w - 1):
            print("红方胜利！")
            over = True
    else:  # 红方持球
        # 判断是否进入蓝方球门
        if y == mid and x == (w - 1):
            print("红方胜利！")
            ball = 'b'  # 交换球权
            over = True
        # 判断乌龙球（进入自家球门）
        if y == mid and x == 0:
            print("蓝方胜利！")
            over = True
    return over

# 通过随机走位判断总的胜率，0为红方、1为蓝方
def robot(index):
    global lens, ball, move_a, move_b
    lens -= 1  # 剩余模拟次数
    to = 0  # 默认不动
    count = {}
    sum = 0
    # 然后统计接下来的所有可能状态：假设对方不动
    if index == 0:  # 红方
        b = goto(move_b[0], move_b[1])
        for i in range(5):
            a = goto(move_a[0], move_a[1], i)
            # 键：持球方(a为红方持球，b为蓝方持球)_红方坐标_蓝方坐标
            key = ball + '_' + str(a[0]) + '-' + str(a[1]) + '_' + str(b[0]) + '-' + str(b[1])
            nums = get_data(key)
            count[key] = nums[0]
            sum += nums[0]
    else:  # 蓝方
        a = goto(move_a[0], move_a[1])
        for i in range(5):
            b = goto(move_b[0], move_b[1], i)
            key = ball + '_' + str(a[0]) + '-' + str(a[1]) + '_' + str(b[0]) + '-' + str(b[1])
            nums = get_data(key)
            count[key] = nums[index]
            sum += nums[index]
    # 统计结果
    print(count)
    # 最大长度
    count_l = len(count)
    if sum == 0:
        # 随机移动
        to = random.randint(0, count_l - 1)
    else:
        # 概率统计
        step: list[float] = []
        step_sum = 0
        # 统计模拟法
        for c in count:
            try:
                # 当前移动方向的概率
                px = count[c] / sum
                step_sum += px
                step.append(step_sum)
            except ZeroDivisionError:
                print("Error: Division by zero occurred while calculating probability.")
                break
        # 通过不同的概率值来确定下一步的动作方向
        rand = random.random()
        for j in range(len(step)):
            if rand <= step[j]:
                to = j
                break
    keys = list(count.keys())
    try:
        name = keys[to]
    except IndexError:
        print("Error: Index out of range when accessing keys.")
        return
    # 值：红方积分、蓝方积分（均默认为0）
    val = [0, 0]
    # 忽略重复动作可以使用：
    data[name] = val
    # 通过键名返回坐标
    print(name)
    names = name.split('_')
    name_a = names[1].split('-')
    name_b = names[2].split('-')
    ya = int(name_a[0])
    xa = int(name_a[1])
    yb = int(name_b[0])
    xb = int(name_b[1])
    # 判断是否结束比赛
    end = False
    if index == 0:
        # 判断红方是否胜利
        end = game_over(ya, xa)
    if index == 1:
        # 判断蓝方是否胜利
        end = game_over(yb, xb)
    if end:
        play(ya, xa, yb, xb)
        # 结束比赛并重新开始
        root.after(1000, start)
    else:
        if lens > 0:
            # 双方球员必须在一个区域内才能进行抢断
            if ya == yb and xa == xb:
                # 交换球权的概率，默认80%
                if random.random() > 0.2:
                    # 进行攻防转换
                    if ball == 'a':
                        ball = 'b'
                    else:
                        ball = 'a'
                print('抢断中！')
            # 显示动画
            play(ya, xa, yb, xb)
            # 继续比赛(每秒递归一次)
            if index == 0:  # 红方移动
                move_a = [ya, xa]
            else:  # 蓝方移动
                move_b = [yb, xb]
            if index == 0:
                root.after(1000, lambda: robot(0))
            if index == 1:
                root.after(1000, lambda: robot(1))
        else:
            # 超时为平局，双方各+1分
            print("双方平局！")
            start()

# 开始比赛
def start():
    global data, lens, move_a, move_b, ball
    data = {}
    lens = size
    move_a = [mid, cen - 1]
    move_b = [mid, cen + 1]
    ball = 'b'
    play(move_a[0], move_a[1], move_b[0], move_b[1])
    root.after(300, lambda: robot(0))  # 启动红方
    root.after(700, lambda: robot(1))  # 启动蓝方

# 获取数据（模拟）
def get_data(key):
    return [0, 0]

# 显示球场
show()
# 开始比赛
start()

root.mainloop()